﻿#ifndef BANDSOLVER_H
#define BANDSOLVER_H

#include <cstdint>
#include <string>
#include <eigenhelper.h>

//DAT文件头的大小
#define SZ_HEAD sizeof(DatInfo)
#define SZ_FLOAT sizeof(float)
//方程组为压缩格式
#define DAT_COMPRESSED 0x202
//方程组为非压缩格式
#define DAT_UNCOMPRESSED 0x102
//DAT文件的Magic Number
#define DAT_MAGIC 0x0c0a8708

//DAT文件头
typedef struct {
    // 数据文件标示
    int32_t id;
    // 数据文件版本号
    int32_t ver;
    // 备用标志
    int32_t id1;
    // 方程组的阶数
    uint32_t n;
    //  上带宽
    uint32_t q;
    //  下带宽
    uint32_t p;
} DatInfo;


//带状矩阵求解器
class BandSolver {
public:
    //求解载入的方程组（需要先调用loadFromFile以载入方程组）
    Vecd solve();

    //输出求解结果（需要先调用solve）
    void printAns(size_t num = 20);

    //求解结果转为字符串（需要先调用solve）
    std::string ansToString(size_t num = 20);

    //从DAT文件中载入方程组
    bool loadFromFile(const std::string &filePath);

public:
    //根据文件信息计算系数矩阵的大小
    static constexpr size_t lenA(DatInfo info);

    //校验文件的正确与完整性
    static constexpr bool datCheck(size_t fileSize, DatInfo info);

    //将非压缩形式的方程组压缩，以便统一处理
    static Matd compress(size_t p, size_t q, const Matd &original);

    //求解压缩格式的带状矩阵
    static Vecd solveCompressed(size_t p, size_t q, const Matd &A, const Vecd &B);

private:
    size_t m_n, m_p, m_q;
    Vecd m_B, m_X;
    Matd m_A;
};


#endif // BANDSOLVER_H
